#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/4/10 9:14
# @Author  : Devin
# @Site    : 
# @File    : prediction.py
# @Software: PyCharm Edu


import pandas
from keras import backend as K
import logging
import json
import sys

sys.path.append("./gen-py")

from AI_pred import Prediction
from train_or_test import Train_or_Evaluate
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

from DataProcessing import get_name_by_program, split_df, get_df_from_cassandra
from model import Data
import time
import configparser
logging.basicConfig(filename='./log/error.log', level=logging.DEBUG)
cf = configparser.ConfigParser()
cf.read("conf/train.conf")

def predict(df, x, cate_col, num_col,class_list,user_id,model_name):
    print(df)
    start_time = time.time()
    columns_list = list(df.columns)
    columns_list.append("predlist") #保存列順序信息
    index_list = list(df.index)     #保存行名信息
    df = df.reset_index(drop=True)
    df_2, name_list = get_name_by_program(df,class_list)
    df_dict = split_df(df_2, name_list)
    df_pred = pandas.DataFrame()
    print("pred_time1: ",(time.time()-start_time))
    for name_by_program in df_dict.keys():
        try:
            data = Data(df_dict[name_by_program],x ,[], cate_col,num_col,name_by_program,user_id,model_name)
            if data.model_exists == False:
                return ["models not exists"]
            test_x1 = data.get_dummies_labeldf(data.x)
            test_x2 = data.column_name_modifier(test_x1, "x")
            print("pred_time2: ",(time.time()-start_time))
            pred = (data.predict(test_x2))
            print("pred_time3: ",(time.time()-start_time))
            df_copy = df_dict[name_by_program].copy()
            df_copy["predlist"] = list(pred)
            print(df_pred, df_copy)
            df_pred = pandas.concat([df_copy,df_pred],axis = 0)
        except Exception as e:
            print ("error: ",str(e))
            pass
        finally:
            K.clear_session()
    df_pred = df_pred.sort_index(axis=0)
    df_pred = pandas.DataFrame(df_pred,columns=columns_list)#恢復列順序，與原輸入DataFrame一一對應
    df_pred.index=index_list                                #將行名與原df一一對應
    print("pred_time4: ",(time.time()-start_time))
    return list(pred)


class Test:

    def predict_by_cassandra(self, json_data):
        print("enter predict_by_cassandra function")
        load_dict = json.loads(json_data)
        try:
            x = load_dict["x"]
            cate_col = load_dict["cate_col"]
            num_col = load_dict["num_col"]
            class_list = load_dict["class"]
            address = load_dict["address"]
            user_id = load_dict["user_id"]
            model_name = load_dict["model_name"]
        except KeyError:
            logging.error("error json in predict_by_cassandra function")

        df = get_df_from_cassandra(address)

        predict_list = predict(df ,x, cate_col, num_col ,class_list,user_id,model_name)
        return predict_list
    
    def predict_by_realtime_data(self,json_data):
        print("enter predict_by_realtime_data function")
        print(json_data)
        load_dict = json.loads(json_data)
        x_data = json.loads(load_dict["x_data"])
        column_list = json.loads(load_dict["x_column_list"])
        cate_col = load_dict["cate_col"]
        num_col = load_dict["num_col"]
        class_list = load_dict["class"]
        user_id = load_dict["user_id"]
        model_name = load_dict["model_name"]
        df = pandas.DataFrame(x_data, columns=column_list)
        print (df)
        input_columns_name = [xx for xx in df.columns if xx not in class_list]
        predict_list = predict(df ,input_columns_name, cate_col, num_col ,class_list,user_id,model_name)
        print(predict_list)
        return predict_list

    def test(self):
        print("just for test")

if __name__ == "__main__":
    handler = Test()
    processor = Prediction.Processor(handler)
    transport = TSocket.TServerSocket(host=cf.get("pred_address", "host"), port=cf.getint("pred_address", "port"))
    tfactory = TTransport.TBufferedTransportFactory()
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()

    server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
    print ("Strating predict server in python")
    server.serve()
    print ("Done")

